/*
 * @File    :   pool.js
 * @Time    :   2024/03/21 19:04:07
 * @Author  :   chakcy
 * @Email   :   947105045@qq.com
 * @description   :   sqlite 连接池
 */

const sqlite3 = require('sqlite3').verbose()
const path = require('path')
const { basePath } = require("../../config")

// 定义 sqlite 连接池类
class sqliteConnectionPool {
    // 构造函数
    constructor(filePath, maxConnections) {
        this.filePath = filePath
        this.maxConnections = maxConnections // 最大连接数
        this.idleTimeout = 300000  // 空闲连接超时时间，单位：毫秒
        this.cleanupInterval = 60000  // 清理空闲连接间隔，单位：毫秒
        this.connections = []  // 存储连接
        this.inUse = new Set()  // 存储正在使用的连接

        // 添加定时任务，定期检测并释放空闲连接
        setInterval(() => {
            this.connections.forEach((connection, index) => {
                if (!this.inUse.has(connection) && this.isConnectionIdle(connection)) {
                    this.connections.splice(index, 1)
                    this.release(connection)
                }
            })
        }, this.cleanupInterval)
    }

    // 获取可用连接
    acquire() {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < this.connections.length; i++) {
                if (!this.inUse.has(this.connections[i])) {
                    if (this.connections[i].lastUsedTime && (Date.now() - this.connections[i].lastUsedTime) > 30000) {
                        // 如果连接空闲时间超过 30 秒，则关闭连接
                        this.release(this.connections[i]);
                        const newDb = new sqlite3.Database(this.filePath, (err) => {
                            if (err) {
                                reject(err);
                            } else {
                                console.log('Connected to the database.');
                                this.inUse.add(newDb);
                                newDb.lastUsedTime = Date.now();
                                resolve(newDb);
                            }
                        });
                        this.connections[i] = newDb;
                        return;
                    } else {
                        this.inUse.add(this.connections[i]);
                        this.connections[i].lastUsedTime = Date.now();
                        resolve(this.connections[i]);
                        return;
                    }
                }
            }
            if (this.connections.length < this.maxConnections) {
                const newDb = new sqlite3.Database(this.filePath, (err) => {
                    if (err) {
                        reject(err);
                    } else {
                        console.log('Connected to the database.');
                        this.connections.push(newDb);
                        this.inUse.add(newDb);
                        newDb.lastUsedTime = Date.now();
                        resolve(newDb);
                    }
                });
            } else {
                // 如果没有可用连接，则抛出错误
                reject(new Error('No available connections in the pool.'));
            }
        });
    }


    // 判断连接是否空闲
    isConnectionIdle(connection) {
        return !this.inUse.has(connection) && (Date.now() - connection.lastUsedTime) > this.idleTimeout
    }

    // 释放连接
    release(db) {
        if (this.inUse.has(db)) {
            db.close((err) => {
                if (err) {
                    console.error(err.message)
                } else {
                    console.log('Connection closed.')
                }
            })
            this.inUse.delete(db)  // 从正在使用中移除
        } else {
            console.error('Attempting to release an unused connection.')
        }
    }



    // 关闭连接池中所有连接
    closeAll() {
        const closePromises = this.connections.map(db =>
            new Promise((resolve, reject) => {
                db.close((err) => {
                    if (err) {
                        console.error('Error closing connection:', err); // 添加错误处理和日志输出
                        reject(err);
                    } else {
                        console.log('Connection closed.')
                        resolve();
                    }
                })
            })
        )
        Promise.all(closePromises).then(() => {
            this.connections = [];
            this.inUse.clear();
            console.log('All connections closed.')
        }).catch(err => {
            console.error('Error closing connections:', err); // 处理关闭连接时的错误
        })
    }
}

// 导出 sqliteConnectionPool 类
module.exports = {
    pool: new sqliteConnectionPool(path.join(basePath, "../../db/database.db"), 5),
    sqliteConnectionPool
}